/*
 * FilterWordBase.cpp
 *
 *  Created on: 2011-4-21
 *      Author: lgw
 */


#include "FilterWordBase.h"

#include <wctype.h>
#include <memory>
#include <string>
#include <algorithm>
#include <cstring>
#include <cstdlib>

namespace Zha
{

	void zeroMemory(void *mem, size_t length)
	{
		memset(mem, 0, length);
	}

	std::wstring NarrowToWide( const std::string &source )
	{
		int len = source.length() + 1;

		std::auto_ptr<wchar_t> buf(new wchar_t[len]);
		zeroMemory( buf.get(), (source.length() + 1) * sizeof(short) );

		setlocale(LC_ALL, "");
		mbstowcs(buf.get(), source.c_str(), len);

		return( buf.get() );
	}

	std::wstring UTF8ToWide( const std::string &source )
	{
		setlocale(LC_ALL, ".UTF8");
		int charsNeeded = mbstowcs(NULL, source.c_str(), 0);
		std::auto_ptr<wchar_t> buf(new wchar_t[charsNeeded + 1]);
		mbstowcs(buf.get(), source.c_str(), charsNeeded);

		buf.get()[charsNeeded] = L'\0';

		return( buf.get() );
	}

	std::wstring StringToUpper(const std::wstring& theString)
	{
		std::wstring tmpStr = theString;
		std::transform(tmpStr.begin(), tmpStr.end(), tmpStr.begin(), towupper);
		return tmpStr;
	}
}

namespace Zha
{

FilterWordBase::Filter::Filter(std::vector<std::string> &fwList) : m_Root(new Node())
{
		for (std::vector<std::string>::iterator it = fwList.begin(); it != fwList.end(); ++it)
		{
			std::wstring wstr = NarrowToWide(*it);
			std::wstring word = ToTrimUpper(wstr);

			if (word.length() > 0)
			{
				Node* node = m_Root;

				for (size_t i = 0; i < word.length(); ++i)
				{
					wchar_t c = word[i];
					if (node->GetChildren().find(c) == node->GetChildren().end())
					{
						Node* child(new Node());
						child->SetKey(c);
						node->GetChildren().insert(std::make_pair(c, child));
					}

					node = node->GetChildren()[c];
				}

				node->SetLeaf(true);
			}
		}
}



bool FilterWordBase::Filter::Find(const std::string &text)
{
	std::wstring wtext = StringToUpper(NarrowToWide(text));

	for (size_t i = 0; i < wtext.length(); ++i)
	{
		if (DoFind(m_Root, i, wtext))
		{
			return true;
		}
	}

	return false;
}

bool FilterWordBase::Filter::DoFind(Node* node, size_t pos, const std::wstring &text)
{
	if (pos < text.length())
	{
		wchar_t c = text[pos];
		if (node && node->GetChildren().find(c) != node->GetChildren().end())
		{
			if (node->GetChildren()[c]->IsLeaf())
			{
				return true;
			}
			else
			{
				return DoFind(node->GetChildren()[c], ++pos, text);
			}
		}
	}

	return false;
}

std::wstring FilterWordBase::Filter::NarrowToWide(const std::string &source)
{
	int len = source.length() + 1;

	std::auto_ptr<wchar_t> buf(new wchar_t[len]);
	memset(buf.get(), 0,  len * sizeof(short));

	//减少库函数setlocale的调用开销
	if (strcmp(getenv("LANG"), setlocale(LC_ALL, NULL)) != 0)
	{
		setlocale(LC_ALL, "");
	}

	mbstowcs(buf.get(), source.c_str(), len);

	return buf.get();
}

std::wstring FilterWordBase::Filter::ToTrimUpper(std::wstring word)
{
	const static std::wstring SPACES = L" \t\r\n";

	word.erase(0, word.find_first_not_of(SPACES));

	size_t idx = word.find_last_not_of(SPACES);
	if( idx != std::wstring::npos )
	{
		word.erase(idx + 1);
	}

	return StringToUpper(word);
}

bool FilterWordBase::Init()
{
	if (m_Filter)
	{
		delete m_Filter;
		m_Filter = NULL;
	}
	int re = Load();

	return re;
}

bool FilterWordBase::Load()
{
	m_Filter = new Filter(m_filterWords);
	return true;
}

void FilterWordBase::AddFilterWord(std::string str)
{
	m_filterWords.push_back(str);
}

int FilterWordBase::Find(const std::string &text)
{
	if (m_Filter)
	{
		return m_Filter->Find(text);
	}

	return 0;
}

}

